all files / src/helpers/ battle.helpers.ts

100% Statements 62/62
94.44% Branches 17/18
100% Functions 19/19
100% Lines 60/60
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113    36× 18× 18× 18×     19×     14×     18×     20×     37×           14× 15×             14×                   14×   14× 14× 14×   14×   14×           19× 17×                          
import { Battle, Game, Suit, Card, PlayersBid, Player, TrumpAnnouncement, CardPattern } from '../game.interfaces';
import { getNextTurn, getPlayerById, getPlayerTotalPoints } from './players.helpers';
import * as _ from 'lodash';
import { getHighestBid } from './bid.helpers';
import { getPointsByCard, getTrumpPointsBySuit, areCardsEqual, getCardsByColor, getCardWithHighestRank, cardsWithSpecificColorExists, toCard } from './cards.helpers';
 
export function getNextTrickTurn(state: Game, Eplayer: string = state.battle.leadPlayer): string {
    const gamePlayers = state.players;
    const { battle } = state;
    return _.reduce(battle.trickCards, (nextPlayer) => getNextTurn(gamePlayers, nextPlayer), player);
}
 
export function getTrumpSuit(battle: Battle): Suit | null {
    return battle.trumpAnnouncements.length > 0 ? battle.trumpAnnouncements[0].suit : null;
}
 
export function isTrumpAnnounced(battle: Battle): boolean {
    return !!getTrumpSuit(battle);
}
 
export function isTableEmpty(battle: Battle): boolean {
    return battle.trickCards.length === 0;
}
 
export function getLeadCard(battle: Battle): CardPattern {
    return battle.trickCards[0];
}
 
export function getCardSuit(card: CardPattern): Suit {
    return toCard(card).suit;
}
 
export function roundPoints(points: number): number {
    const minor = (points % 10);
    const major = points - minor;
 
    return minor >= 5 ? major + 10 : major;
}
 
export function calculateTrumpPointsForPlayer(state: Game, player: string): number {
    return _.chain(state.battle.trumpAnnouncements)
        .filter((trumpAnnouncement: TrumpAnnouncement) => trumpAnnouncement.player === player)
        .map('suit')
        .map(getTrumpPointsBySuit)
        .sum()
        .value();  
}
 
export function calculateCardPointsForPlayer(state: Game, player: string): number {
    return _.chain(state.battle.wonCards[player])
        .map(toCard)
        .map(getPointsByCard)
        .sum()
        .value();
}
 
export function getTotalWonCards(state: Game): number {
    return _.reduce(state.battle.wonCards, (totalCards, cards) => {
        return totalCards + cards.length;
    }, 0);
}
 
export function calculatePointsByPlayer(state: Game, player: string): number {
    const {player: leadPlayer, bid: leadBidValue}: PlayersBid = getHighestBid(state.bid);
    
    const playerPoints = getPlayerTotalPoints(getPlayerById(state.players, player));
    const trumpPoints = calculateTrumpPointsForPlayer(state, player);
    const cardPoints = calculateCardPointsForPlayer(state, player);
 
    const totalPoints = trumpPoints + cardPoints;
    
    if (leadPlayer === player) {
        return (totalPoints >= leadBidValue) ? leadBidValue : -leadBidValue
    } else {
        return playerPoints >= state.settings.barrelPointsLimit ? 0 : roundPoints(totalPoints);
    }
}
 
export function getPlayerByTrickCard(trickCard: CardPattern, state: Game): string {
    const { battle: { leadPlayer, trickCards }, players } = state;
 
    return _.chain(trickCards)
        .dropRightWhile(card => !areCardsEqual(card, trickCard))
        .reduce((player: string) => player ? getNextTurn(players, player) : leadPlayer, null)
        .value();
}
 
export function getTrickWinner(state: Game): string {
    const { battle } = state;
    const { trickCards } = battle;
    const leadCard: CardPattern = getLeadCard(battle);
    let winnerPlayerId = null;
    
    if(isTrumpAnnounced(battle)) {
        const trumpSuit: Suit = getTrumpSuit(battle);
        if (cardsWithSpecificColorExists(trickCards, trumpSuit)) {
            matchBySuit(trumpSuit);
        } else {
            //no trump cards taking part in the trick, so ordinary color matching flow:
            matchBySuit(getCardSuit(leadCard));
        }
    } else {
        matchBySuit(getCardSuit(leadCard));
    }
 
    return winnerPlayerId;
 
    function matchBySuit(suit: Suit) {
        const cardsMatchedByColor = getCardsByColor(trickCards, getCardSuit(leadCard));
        const highestRankedCard = getCardWithHighestRank(cardsMatchedByColor);
        winnerPlayerId = getPlayerByTrickCard(highestRankedCard, state);
    }
}